package cn.tedu.review;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*复写售票方案2*/
public class TestRunnable {
    public static void main(String[] args) {
        TicketRunnable t = new TicketRunnable();
       /* Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        Thread t4=new Thread(t);
        t1.start();
        t2.start();
        t3.start();
        t4.start();*/
        /*Excutors是用来辅助创建线程池的工具类对象
        *常用方法是newFixedThreadPool(int)这个方法可以创建指定数目的线程池对象
        *创建出来的线程池对象是ExecutorService:这个池子用来新建/启动/存储/销毁线程  */
        ExecutorService pool = Executors.newFixedThreadPool(5);
        for (int i=0;i<5;i++){
            /*execute()是让线程池中的线程来执行业务,每次调用这个方法
            * 都会讲一个线程加入到就绪队伍中,但注意,具体执行还得看OD是否选中*/
            pool.execute(t);/*本法的参数就是我们的业务,也就是业务类对象target*/
        }
    }
}
/*1.多线程出现安全问题的原因:多线程程序+共享数据+多条语句操作共享数据
* 2.同步锁相当于给容易出错的代码加锁,包裹了所有坑会出现数据安全的代码
* 加锁之后,就有了同步(排队)的效果,加锁需要考虑:
* 锁的范围:不能太大,效率低.不能太小,锁不住.
* 注意!!!多个线程间必须使用同一把锁,否则锁不住!!!*/
class TicketRunnable implements Runnable{
    int ticket=100;
    /*这种写法不对*/
    //Object o=new Object();
    //Cat c=new Cat();
    @Override
    public void run() {
        while (true){
            /*3.同步代码块
            * synchronized (唯一的锁对象){会出现安全隐患的所有代码}
            * 同步代码块在同一时刻,同一资源只会被一个线程对象独享*/
            /**synchronized (new Object()){*/
            /*这种写法不对,相当于每个线程进来时,执行这句话都会new一个新的锁对象,
            * 多个线程间使用的并不是同一个唯一的锁对象,所以锁不住*/
            synchronized (TicketRunnable.class){
                if(ticket>0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+ticket--);

                }
                 if (ticket<=0)break;
            }
        }
    }
}
class Cat{

}